package cn.clq.ymcc.service.impl;

import cn.clq.ymcc.constants.CommonConstants;
import cn.clq.ymcc.constants.SmsCodeConstants;
import cn.clq.ymcc.constants.YmccError;
import cn.clq.ymcc.domain.Login;
import cn.clq.ymcc.domain.MessageSms;
import cn.clq.ymcc.dto.RedisRegisterDto;
import cn.clq.ymcc.dto.RegisterDto;
import cn.clq.ymcc.service.IMessageSmsService;
import cn.clq.ymcc.service.IMessageVerifyCodeService;
import cn.clq.ymcc.util.AssertUtil;
import cn.clq.ymcc.util.StrUtils;
import cn.clq.ymcc.util.VerifyCodeUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author clqlongbao
 * @version 1.0
 * @description: TODO
 * @date 2022/7/15 19:26
 */
@Service
@Slf4j
public class MessageVerifyCodeServiceImpl implements IMessageVerifyCodeService {
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private IMessageSmsService messageSmsService;
    @Autowired
    private SmsCodeConstants smsCodeConstants;
    /**
     * @description: 获取图片验证码
     * @param: imageCodeKey
     * @return: java.lang.String
     * @author clqlongbao
     * @date: 2022/7/15 19:26
     */
    @Override
    public String imageCode(String imageCodeKey) {
        //产生验证码的位数
        String code = StrUtils.getComplexRandomString(4);
        //将数据保存到redis，设置过期时间  key是uuid
        redisTemplate.opsForValue().set(
                imageCodeKey,//前端传递的UUID
                code, //图片中显示的码
                300,//过期时间
                TimeUnit.SECONDS);//过期时间的单位
        //使用2D引擎把code画成图
        //把图使用Base64编码成字符串
        //返回Base64编码的字符串
        return VerifyCodeUtils.verifyCode(100, 38, code);
    }

    /**
     * @description: 发送短息验证码
     * @param: dto
     * @return: void
     * @author clqlongbao
     * @date: 2022/7/16 23:55
     */
    @Override
    public void sendSmsCode(RegisterDto dto) {
        String mobile = dto.getMobile();
        String imageCode = dto.getImageCode();
        String registerImageCodeKey = dto.getRegisterImageCodeKey();
        //1.先校验黑名单
        //根据mobile查询t_message_sms表格中该数据的black
        //messageSmsService
        MessageSms messageSms = selectMessageSmsByMobile(mobile);
        AssertUtil.isNull(messageSms,YmccError.COMMON_MOBILE_BLACKLIST.getMessage());//你已被网站拉黑，请联系客服解封
        //2.校验图形验证码
        String imageCodeTmp = (String)redisTemplate.opsForValue().get(registerImageCodeKey);
        //获取不到说明验证码已经过期了
        AssertUtil.isNotNull(imageCodeTmp, YmccError.COMMON_MOBILE_IMAGECODE_EXPIRED.getMessage());//图形验证码已经过期，请重新获取
        AssertUtil.isEqualsIgnoreCase(imageCode,imageCodeTmp,YmccError.COMMON_MOBILE_IMAGECODE_WRONG.getMessage());//图形验证码输入错误
        //3.校验短信验证码
        Date now = new Date();
        String key = String.format(CommonConstants.REGISTER_MOBILE_PREFIX,mobile);
        Object o = redisTemplate.opsForValue().get(key);
        if(o!=null){
            //拿到了说明发送过验证码，且还在有效期中
            RedisRegisterDto redisRegisterDto = (RedisRegisterDto) o;
            AssertUtil.isTrue((now.getTime()-redisRegisterDto.getTime())/1000 > smsCodeConstants.getInterval(),YmccError.COMMON_MOBILE_SMSCODE_INTERVAL.getMessage());//两次发送短信验证码的时间间隔必须大于60秒
        }
        //4.生成短信验证码,存到redis
        String smsCode = StrUtils.getRandomString(smsCodeConstants.getSize());
        RedisRegisterDto redisRegisterDto = new RedisRegisterDto(smsCode,now.getTime());
        redisTemplate.opsForValue().set(
                key,
                redisRegisterDto,
                smsCodeConstants.getExpire(),
                TimeUnit.SECONDS);
        //5.发送手机短信
        String message = String.format(smsCodeConstants.getSmsmessage(), smsCode);
        log.info(message);
        //6.存储发送的短信信息到数据库
        saveSmsMessage(message);
    }




    private void saveSmsMessage(String message) {
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(smsCodeConstants.getTitle());
        messageSms.setContent(message);
        messageSms.getSendTime();
        //在实现类中获取请求体使用RequestContextHolder,如果是在Controller中获取ip，需要传入HttpServletRequest
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        messageSms.setIp(request.getRemoteAddr());//获取IP地址
        messageSmsService.insert(messageSms);
    }

    private MessageSms selectMessageSmsByMobile(String mobile) {
        Wrapper<MessageSms> tWrapper = new EntityWrapper();
//        tWrapper.eq("mobile",mobile);  // where mobile = 123123
//        tWrapper.eq("black",0);  // where black = 0
        HashMap<String, Object> map = new HashMap<>();
        map.put("mobile",mobile);
        map.put("black",0);
        tWrapper.allEq(map);
        return messageSmsService.selectOne(tWrapper);
    }
}
